package com.ykh.spring.impl;

import com.ykh.spring.Calculate;
import com.ykh.spring.impl.CalculateImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: YKH
 * Date: 2022-08-24
 * Time: 10:20
 */
//1.创建一个生成 动态代理类的工厂
public class PraxyFactory {
   //2. 创建目标方法的对象
    Object target;

    //3. 生成构造方法
    public PraxyFactory(Object target) {
        this.target = target;
    }

    /**4.生产获取代理对象的方法
     * a> 通过java.lang.reflect 包下的 Proxy.newProxyInstance() 方法生成 代理对象 ,
     * b> 方法中的三个参数 :
     *       ClassLoader loader :    加载动态生成的代理类的类加载器
     *       Class<?>[] interfaces : 代理的对象所实现的接口的数组
     *       InvocationHandler h) :   设置代理对象实现目标方法的过程, 既如何重写 实现接口中的抽象方法
     *
     */
    public Object getPraxy() {
        //1) 通过反射获得目标方法的类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        //2) 获得代理对象所实现的接口的数组
        Class<?>[] interfaces = target.getClass().getInterfaces();
        //3) 重写实现的接口中的方法
        InvocationHandler h = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /**
                 *  praxy : 代理的对象
                 *  method: 代理对象中需要重写的方法
                 *  args :  需要重写的方法中的参数
                 */
                Object result = null;
                try {
                    System.out.println("[动态代理][日志] "+method.getName()+"参数："+ Arrays.toString(args));
                    //调用通过目标对象调用目标方法
                    result = method.invoke(target, args);
                    System.out.println("[动态代理][日志] "+method.getName()+"，结果："+ result);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("[动态代理][日志] "+method.getName()+"，异常："+ e);
                } finally {
                    System.out.println("[动态代理][日志] "+method.getName()+"，运行结束：");
                }
                return result;
            }
        };
        //返回生成的 代理对象
        return Proxy.newProxyInstance(classLoader,interfaces,h);
    }
}
